//
//  UserDefaultsHelper.swift
//  XWClassroom
//
//  Created by xianquan on 2023/11/20.
//

import Foundation


public protocol UserDefaultsSettable {
    associatedtype defaultKeys: RawRepresentable
}

public extension UserDefaultsSettable where defaultKeys.RawValue==String {
    // string
    static func set(value: String?, forKey key: defaultKeys, extra: String? = nil) {
        UserDefaults.standard.set(value, forKey: keyValue(key: key, extra: extra))
    }
    static func string(forKey key: defaultKeys, extra: String? = nil) -> String? {
        return UserDefaults.standard.string(forKey: keyValue(key: key, extra: extra))
    }
    // int
    static func set(value: Int?, forKey key: defaultKeys, extra: String? = nil){
        UserDefaults.standard.set(value, forKey: keyValue(key: key, extra: extra))
    }
    static func integer(forKey key: defaultKeys, extra: String? = nil) -> Int {
        UserDefaults.standard.integer(forKey: keyValue(key: key, extra: extra))
    }
    //double
    static func set(value: Double?, forKey key: defaultKeys, extra: String? = nil){
        UserDefaults.standard.set(value, forKey: keyValue(key: key, extra: extra))
    }
    static func double(forKey key: defaultKeys, extra: String? = nil) -> Double {
        UserDefaults.standard.double(forKey: keyValue(key: key, extra: extra))
    }
    // float
    static func set(value: Float?, forKey key: defaultKeys, extra: String? = nil){
        UserDefaults.standard.set(value, forKey: keyValue(key: key, extra: extra))
    }
    static func float(forKey key: defaultKeys, extra: String? = nil) -> Float {
        UserDefaults.standard.float(forKey: keyValue(key: key, extra: extra))
    }
    // bool
    static func set(value: Bool?, forKey key: defaultKeys, extra: String? = nil){
        
        UserDefaults.standard.set(value, forKey: keyValue(key: key, extra: extra))
    }
    static func bool(forKey key: defaultKeys, extra: String? = nil) -> Bool {
        return UserDefaults.standard.bool(forKey: keyValue(key: key, extra: extra))
    }
    // url
    static func set(value: URL?, forKey key: defaultKeys, extra: String? = nil){
        UserDefaults.standard.set(value, forKey: keyValue(key: key, extra: extra))
    }
    static func url(forKey key: defaultKeys, extra: String? = nil) -> URL? {
        UserDefaults.standard.url(forKey: keyValue(key: key, extra: extra))
    }
    // any
    static func set(value: Any?, forKey key: defaultKeys, extra: String? = nil){
        UserDefaults.standard.set(value, forKey: keyValue(key: key, extra: extra))
    }
    static func object(forKey key: defaultKeys, extra: String? = nil) -> Any? {
        UserDefaults.standard.object(forKey: keyValue(key: key, extra: extra))
    }
    
    static func array(forKey key: defaultKeys, extra: String? = nil) -> [Any]? {
        UserDefaults.standard.array(forKey: keyValue(key: key, extra: extra))
    }
    
    static func dictionary(forKey key: defaultKeys, extra: String? = nil) -> [String : Any]? {
        UserDefaults.standard.dictionary(forKey: keyValue(key: key, extra: extra))
    }
    
    static func data(forKey key: defaultKeys, extra: String? = nil) -> Data? {
        UserDefaults.standard.data(forKey: keyValue(key: key, extra: extra))
    }
    
    private static func keyValue(key: defaultKeys, extra: String?) -> String{
        "\(self).\(key.rawValue)\(extra ?? "")"
    }
    
    
}

public extension UserDefaults {
    
    struct DeviceModule: UserDefaultsSettable {
        public enum defaultKeys: String {
            case deviceName
            case isNotFirstLaunch
        }
    }
    
    struct LoginModule: UserDefaultsSettable {
        public enum defaultKeys: String {
            case token
            /// 是否游客
            case isTourist
            /// 是否打开游客支付
            case isTouristPay
        }
    }
    
    struct PointReadingModule: UserDefaultsSettable {
        public enum defaultKeys: String {
            case currentStudy
            case showGuide
        }
    }
    
    struct DictionaryModule: UserDefaultsSettable {
        public enum defaultKeys: String {
            case unfamiliarWordList
            case historyWords
            case guide
        }
    }
    
    struct DictationModule: UserDefaultsSettable {
        public enum defaultKeys: String{
            case guide
            case timeInterval
            case unfamiliarWordList
        }
    }
    
    struct NewWordModule: UserDefaultsSettable {
        public enum defaultKeys: String {
            case unfamiliarWordList
        }
    }
    
    struct VideoModule: UserDefaultsSettable {
        public enum defaultKeys: String{
            case guide
            case lastPlayTime
            case lastPlayVideo
        }
    }
    
    struct VipCenterModule: UserDefaultsSettable {
        public enum defaultKeys: String {
            case payOrder
            case productList
            case hasBuyTyVip
        }
    }
    
    struct HomeModule: UserDefaultsSettable {
        public enum defaultKeys: String {
            case catalogIdMap
            /// 新手指引，默认0，首次登录后设置为1，显示后设置为2，如果登录后已经有历史记录，设置为2，为2表示已经显示过历史记录
            case guidance
            case guidanceNew
        }
    }
    
    struct RememberWordModule: UserDefaultsSettable {
        public enum defaultKeys: String {
            case touristTestScore
        }
    }
    // 按模块划分结构体，eg:
//    struct LoginModule: UserDefaultsSettable {
//        enum defaultKeys: String {
//            case token
//            case userId
//        }
//    }
}
